using System;
using System.Collections.Generic;
using System.Text;
using cuberga.Workflow;
using cuberga.Utils;

namespace cuberga.GA
{
    class RouletteWheelSelector: ICoreProcess
    {
        private PermutationPopulation _population;

        public void Perform()
        {
            // ToDo - Convert algo to code
            Console.WriteLine("RWS");
            int parentsCount = 2;

            _population = (PermutationPopulation)BlackBoard.Instance.Read("Population"); // by reference
            PermutationPopulation parents = SelectParents(parentsCount);
            BlackBoard.Instance.Write("Parents", parents);
        }

        private PermutationPopulation SelectParents(int parentsCount)
        {
            PermutationPopulation selectedParents = new PermutationPopulation();
            for (int i = 0; i < parentsCount; i++)
            {
                Genotype newParent = SelectParent();
                selectedParents.Add(newParent.Clone());
            }

            return selectedParents;
        }

        private Genotype SelectParent()
        {
            double rndPoint = GetTotalSum() * Rand.Instance.NextDouble();
            double curSum = 0;

            foreach (Genotype genotype in _population) {
                curSum += genotype.GetFitness();
                if (curSum >= rndPoint)
                    return genotype;
            }
            // This is just in case anything goes wrong. 
            // Normally program flow shouldn't reach this point.
            throw new ArgumentException(
                "Unexpected error while parent selection. Population count doesn't match algorithm needs");
        }

        private double GetTotalSum()
        {
            double dTotalSum = 0;
            foreach (Genotype genotype in _population)
                dTotalSum += genotype.GetFitness();

            return dTotalSum;
        }

    }
}
